package com.feiyuan.core.service.impl;

import com.feiyuan.core.mapper.SysQuartzJobMapper;
import com.feiyuan.core.pojo.entity.SysQuartzJob;
import com.feiyuan.core.service.SysQuartzJobService;
import com.feiyuan.core.utils.Constant;
import com.feiyuan.core.utils.ScheduleUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 任务调度
 */
@Service
public class SysQuartzJobServiceImpl extends ServiceImpl<SysQuartzJobMapper, SysQuartzJob> implements SysQuartzJobService {

    @Autowired
    private Scheduler scheduler;

    /**
     * 项目启动时，初始化定时器
     */
    @PostConstruct
    public void init(){
        List<SysQuartzJob> scheduleJobList = this.list();
        for(SysQuartzJob scheduleJob : scheduleJobList){
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
            //如果不存在，则创建
            if(cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            }else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }

    @Override
    public IPage<SysQuartzJob> listPage(Integer page, Integer limit) {
        IPage<SysQuartzJob> sysQuartzJobPage = this.baseMapper.selectPage(new Page<SysQuartzJob>(page, limit), new QueryWrapper<SysQuartzJob>());
        return sysQuartzJobPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object saveOrUpdateJob(SysQuartzJob quartzJob) {
        if (quartzJob.getId() != null) {
            this.updateJob(quartzJob);
        } else {
            this.saveJob(quartzJob);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object removeJob(Long id) {
        this.baseMapper.deleteById(id);

        ScheduleUtils.deleteScheduleJob(scheduler, id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object stopJob(Long id) {
        SysQuartzJob job = this.baseMapper.selectById(id);
        job.setUpdateTime(LocalDateTime.now());
        job.setStatus(Constant.ScheduleStatus.PAUSE.getValue());
        baseMapper.updateById(job);

        ScheduleUtils.pauseJob(scheduler, id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object resumeJob(Long id) {
        SysQuartzJob job = this.baseMapper.selectById(id);
        job.setUpdateTime(LocalDateTime.now());
        job.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
        baseMapper.updateById(job);

        ScheduleUtils.resumeJob(scheduler, id);
        return true;
    }

    @Override
    public Object runJob(Long id) {
        SysQuartzJob sysQuartzJob = this.baseMapper.selectById(id);
        ScheduleUtils.run(scheduler, sysQuartzJob);
        return true;
    }

    /**
     * 保存定时任务
     * @param quartzJob
     */
    private void saveJob(SysQuartzJob quartzJob) {
        this.save(quartzJob);

        ScheduleUtils.createScheduleJob(scheduler, quartzJob);
    }

    /**
     * 修改定时任务
     * @param quartzJob
     */
    private void updateJob(SysQuartzJob quartzJob) {
        this.updateById(quartzJob);

        ScheduleUtils.updateScheduleJob(scheduler, quartzJob);
    }
}
